#include "ContextEGL2.h"

#include <stdio.h>

#ifdef _WIN32
#include <windows.h>
#include <TCHAR.h>
#else
// for linux
#endif

static bool TestEGLError(char* pszLocation)
{
  EGLint iErr = eglGetError();
  if (iErr != EGL_SUCCESS)
  {
    printf("%s failed (%d).\n", pszLocation, iErr);
    return false;
  }

  return true;
}

bool ContextEGL2::init(WindowInterface* window)
{
  hWnd = window->handle();
  eglWindow = (EGLNativeWindowType)hWnd;

#ifdef _WIN32
  hDC = GetDC(hWnd);
  if (!hDC)
  {
    MessageBox(0, _T("Failed to create the device context"), _T("Error"), MB_OK|MB_ICONEXCLAMATION);
    return false;
  }
  eglDisplay = eglGetDisplay((EGLNativeDisplayType)hDC);
  if(eglDisplay == EGL_NO_DISPLAY)
    eglDisplay = eglGetDisplay((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY);
#else
  eglDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
#endif


  EGLint iMajorVersion, iMinorVersion;
  if (!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion))
  {
    TestEGLError("eglInitialize() failed.");
    return false;
  }

  eglBindAPI(EGL_OPENGL_ES_API);

  int i = 0;
#ifdef _LINUX_CANMORE
  pi32ConfigAttribs[i++] = EGL_BUFFER_SIZE;
  pi32ConfigAttribs[i++] = EGL_DONT_CARE;
  pi32ConfigAttribs[i++] = EGL_RED_SIZE;
  pi32ConfigAttribs[i++] = 8;
  pi32ConfigAttribs[i++] = EGL_GREEN_SIZE;
  pi32ConfigAttribs[i++] = 8;
  pi32ConfigAttribs[i++] = EGL_BLUE_SIZE;
  pi32ConfigAttribs[i++] = 8;
#else // linux desktop / windows
  pi32ConfigAttribs[i++] = EGL_LEVEL;
  pi32ConfigAttribs[i++] = 0;
  pi32ConfigAttribs[i++] = EGL_SURFACE_TYPE;
  pi32ConfigAttribs[i++] = EGL_WINDOW_BIT;
  pi32ConfigAttribs[i++] = EGL_NATIVE_RENDERABLE;
  pi32ConfigAttribs[i++] = EGL_FALSE;
#endif
  pi32ConfigAttribs[i++] = EGL_ALPHA_SIZE;
  pi32ConfigAttribs[i++] = (flag&CF_ALPHA) ? 8 : EGL_DONT_CARE;
  pi32ConfigAttribs[i++] = EGL_DEPTH_SIZE;
  pi32ConfigAttribs[i++] = (flag&CF_DEPTH) ? 16 : EGL_DONT_CARE;
  pi32ConfigAttribs[i++] = EGL_STENCIL_SIZE;
  pi32ConfigAttribs[i++] = (flag&CF_STENCIL) ? 8 : EGL_DONT_CARE;
  pi32ConfigAttribs[i++] = EGL_SAMPLE_BUFFERS;
  pi32ConfigAttribs[i++] = (flag&CF_MULTISAMPLE) ? 1 : 0;

  pi32ConfigAttribs[i++] = EGL_RENDERABLE_TYPE;
  pi32ConfigAttribs[i++] = EGL_OPENGL_ES2_BIT;
  pi32ConfigAttribs[i++] = EGL_NONE;

  /*
  Step 4 - Find a config that matches all requirements.
  eglChooseConfig provides a list of all available configurations
  that meet or exceed the requirements given as the second
  argument. In most cases we just want the first config that meets
  all criteria, so we can limit the number of configs returned to 1.
  */
  int iConfigs;
  if (!eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs) || (!iConfigs))
  {
    TestEGLError("eglChooseConfig() failed.");
    return false;
  }

  eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, eglWindow, NULL);

  if(eglSurface == EGL_NO_SURFACE)
  {
    eglGetError(); // Clear error
    eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, NULL, NULL);
  }

  if (!TestEGLError("eglCreateWindowSurface"))
  {
    return false;
  }

  EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
  eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, ai32ContextAttribs);
  if (!TestEGLError("eglCreateContext"))
  {
    return false;
  }

  eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
  if (!TestEGLError("eglMakeCurrent"))
  {
    return false;
  }

  return true;
}

void ContextEGL2::shutdown()
{
  //eglDestroyContext(eglDisplay, eglContext);
  //eglDestroySurface(eglDisplay, eglSurface);

  eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  eglTerminate(eglDisplay);

#ifdef _WIN32
  // Release the device context
  if (hDC) ReleaseDC(hWnd, hDC);
#endif
}

void ContextEGL2::update()
{
  eglSwapBuffers(eglDisplay, eglSurface);
}
